import { memo, useCallback, useState } from 'react';
import type { FC, PropsWithChildren } from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';
import {
  Avatar,
  Button,
  Descriptions,
  Form,
  Input,
  message,
  Modal,
  Upload,
} from 'antd';
import type { UploadProps } from 'antd';
import * as yup from 'yup';
import { API_BASEURL } from '@/constants/api';
import { phoneRegexString } from '@/constants/regexp';
import { resChangeUserinfo } from '@/services/user';
import { authStore, useAuthStore } from '@/store/authStore';
import { userStore, useUserStore } from '@/store/userStore';
import { EditOutlined } from '@ant-design/icons';
import { yupResolver } from '@hookform/resolvers/yup';
import { useRequest } from 'ahooks';
import { useRecoilValue } from 'recoil';
import ProfileContainer from '@/components/ProfileContainer';
import RxButton from '@/components/RxForm/RxButton';
import RxCodeInput from '@/components/RxForm/RxCodeInput';
import RxEmailCode from '@/components/RxForm/RxEmailCode';
import RxInput from '@/components/RxForm/RxInput';
import { formatPhone } from '@/utils/format';
import './index.scss';
import EditModal from "@/components/EditModal";

const AutoInput: FC<
  PropsWithChildren<{
    defaultValue: string;
    name: 'name' | 'sign';
    maxLength?: number;
    minLength?: number;
  }>
> = ({ defaultValue, name, maxLength, minLength }) => {
  const [bordered, setBordered] = useState(false);
  const [value, setValue] = useState(defaultValue);
  const { changeUserinfo } = useUserStore();

  return (
    <Input
      value={value}
      bordered={bordered}
      onChange={(e) => {
        setValue(e.target.value);
      }}
      onFocus={() => {
        setBordered(true);
      }}
      maxLength={maxLength}
      minLength={minLength}
      onBlur={() => {
        setBordered(false);
        if (value && value !== defaultValue) {
          changeUserinfo.changeUserinfo({ [name]: value });
        } else {
          setValue(defaultValue);
        }
      }}
      disabled={changeUserinfo.loading}
    />
  );
};

type ModalInfo = {
  show: boolean;
  name: 'phone' | 'email';
};

const UserinfoPage: FC<PropsWithChildren<{}>> = () => {
  const userinfo = useRecoilValue(userStore);
  const auth = useRecoilValue(authStore);
  const { getUserinfo } = useUserStore();

  const [modalInfo, setModalInfo] = useState<ModalInfo>({
    show: false,
    name: 'phone',
  });

  const props: UploadProps = {
    name: 'file',
    action: API_BASEURL + '/user/avatar',
    method: 'PATCH',
    showUploadList: false,
    headers: {
      authorization: 'Bearer ' + auth.token,
    },
    maxCount: 1,
    onChange(info) {
      if (info.file.status === 'done') {
        message.success('头像修改成功');
        getUserinfo();
      } else if (info.file.status === 'error') {
        message.error(`头像修改失败`);
      }
    },
  };
  const onCancel = () => {
    setModalInfo({ ...modalInfo, show: false });
  };
  return (
    <ProfileContainer title={'个人中心'}>
      <Descriptions title={'基本信息'} column={2} className={'px-10 mt-4'}>
        <Descriptions.Item label="头像">
          <Upload {...props}>
            <Avatar src={userinfo.avatar} size={50} />
          </Upload>
        </Descriptions.Item>
        <Descriptions.Item label="账户名">
          {userinfo.username}
        </Descriptions.Item>
        <Descriptions.Item label="昵称" className={'userinfo-item'}>
          <div className={'w-64'}>
            <AutoInput
              defaultValue={userinfo.name}
              name={'name'}
              maxLength={12}
            />
          </div>
        </Descriptions.Item>
        <Descriptions.Item label="签名" className={'userinfo-item'}>
          <AutoInput defaultValue={userinfo.sign} name={'sign'} />
        </Descriptions.Item>
        <Descriptions.Item label="手机" className={'group'}>
          <div>
            {userinfo.phone}
            <span className={'hidden group-hover:inline-block'}>
              <Button
                size={'small'}
                type={'link'}
                onClick={() => {
                  setModalInfo({ show: true, name: 'phone' });
                }}
                icon={<EditOutlined />}
              />
            </span>
          </div>
        </Descriptions.Item>
        <Descriptions.Item label="邮箱" className={'group'}>
          <div>
            {userinfo.email}
            <span className={'hidden group-hover:inline-block'}>
              <Button
                size={'small'}
                type={'link'}
                onClick={() => {
                  setModalInfo({ show: true, name: 'email' });
                }}
                icon={<EditOutlined />}
              />
            </span>
          </div>
        </Descriptions.Item>
      </Descriptions>
      <EditModal
        isModalOpen={modalInfo.show}
        onOk={() => {
          setModalInfo({ ...modalInfo, show: false });
        }}
        onCancel={onCancel}
        title={modalInfo.name === 'phone' ? '绑定手机' : '绑定邮箱'}
      >
        {modalInfo.name === 'phone' ? (
          <EditPhoneForm onCancel={onCancel} />
        ) : (
          <EditEmailForm onCancel={onCancel} />
        )}
      </EditModal>
    </ProfileContainer>
  );
};

const schema = yup
  .object({
    phone: yup.string().matches(phoneRegexString, '手机格式错误').required(),
    code: yup.string().required(),
  })
  .required();

const defaultValues: API.ChangePhoneParams = {
  phone: '',
  code: '',
};

const EditPhoneForm: FC<PropsWithChildren<{ onCancel: Function }>> = ({
  onCancel,
}) => {
  const { control, handleSubmit, trigger, resetField } =
    useForm<API.LoginPhoneParams>({
      resolver: yupResolver(schema),
      defaultValues,
      mode: 'all',
      criteriaMode: 'all',
    });

  const {
    changePhone: { changePhone, loading },
  } = useAuthStore();

  const { getUserinfo } = useUserStore();

  const onSubmit: SubmitHandler<API.ChangePhoneParams> = useCallback(
    (values) => {
      values.phone = formatPhone(values.phone);
      changePhone(values)
        .then(() => {
          getUserinfo();
          onCancel();
        })
        .finally(() => {
          resetField('code');
        })
        .catch(() => {
          message.error('绑定手机失败');
        });
    },
    [changePhone]
  );

  return (
    <Form onFinish={handleSubmit(onSubmit)}>
      <RxInput
        name={'phone'}
        placeholder={'手机号'}
        control={control}
        addonBefore="+86"
      />
      <RxCodeInput
        name={'code'}
        placeholder={'验证码'}
        control={control}
        trigger={trigger}
      />
      <RxButton loading={loading}>绑定手机</RxButton>
    </Form>
  );
};

const emailSchema = yup
  .object({
    email: yup.string().email().required(),
    code: yup.string().required(),
  })
  .required();

const emailDefaultValues: API.ChangeEmailParams = {
  email: '',
  code: '',
};

const EditEmailForm: FC<PropsWithChildren<{ onCancel: Function }>> = ({
  onCancel,
}) => {
  const { control, handleSubmit, trigger, resetField } =
    useForm<API.ChangeEmailParams>({
      resolver: yupResolver(emailSchema),
      defaultValues: emailDefaultValues,
      mode: 'all',
      criteriaMode: 'all',
    });

  const {
    changeEmail: { changeEmail, loading },
  } = useAuthStore();

  const { getUserinfo } = useUserStore();

  const onSubmit: SubmitHandler<API.ChangeEmailParams> = useCallback(
    (values) => {
      changeEmail(values)
        .then(() => {
          getUserinfo();
          onCancel();
        })
        .finally(() => {
          resetField('code');
        })
        .catch(() => {
          message.error('绑定邮箱失败');
        });
    },
    [changeEmail]
  );

  return (
    <Form onFinish={handleSubmit(onSubmit)}>
      <RxInput name={'email'} placeholder={'邮箱'} control={control} />
      <RxEmailCode
        name={'code'}
        placeholder={'验证码'}
        control={control}
        trigger={trigger}
      />
      <RxButton loading={loading}> 绑定邮箱</RxButton>
    </Form>
  );
};

export default memo(UserinfoPage);
